home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / ar / shar < prev    next >
Encoding:
Text File  |  1990-11-16  |  67.9 KB  |  2,573 lines

  1. #--------------------------------CUT HERE-------------------------------------
  2. #! /bin/sh
  3. #
  4. # This is a shell archive.  Save this into a file, edit it
  5. # and delete all lines above this comment.  Then give this
  6. # file to sh by executing the command "sh file".  The files
  7. # will be extracted into the current directory owned by
  8. # you with default permissions.
  9. #
  10. # The files contained herein are:
  11. #
  12. # -rw-rw-r--  1 kupfer      66179 Nov 15 22:29 ar.diffs
  13. #
  14. echo 'x - ar.diffs'
  15. if test -f ar.diffs; then echo 'shar: not overwriting ar.diffs'; else
  16. sed 's/^X//' << '________This_Is_The_END________' > ar.diffs
  17. X*** /tmp/,RCSt1532831    Thu Nov 15 22:29:13 1990
  18. X--- ar.c    Mon Nov 12 11:08:49 1990
  19. X***************
  20. X*** 15,25 ****
  21. X--- 15,32 ----
  22. X     along with this program; if not, write to the Free Software
  23. X     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  24. X  
  25. X+ #ifndef lint
  26. X+ static char rcsid[] = "$Header: /sprite/src/cmds/ar/RCS/ar.c,v 1.6 90/11/12 11:08:45 kupfer Exp $";
  27. X+ #endif
  28. X+ 
  29. X  #include <stdio.h>
  30. X  #include <ar.h>
  31. X  #include <errno.h>
  32. X  #include <sys/types.h>
  33. X  #include <sys/stat.h>
  34. X+ #include <string.h>
  35. X+ #include <bstring.h>
  36. X+ #include <assert.h>
  37. X  
  38. X  #if !defined(A_OUT) && !defined(MACH_O)
  39. X  #define A_OUT
  40. X***************
  41. X*** 64,76 ****
  42. X  #define    bzero(s, size)            memset((s), 0, (size))
  43. X  #endif
  44. X  
  45. X! /* Locking is normally disabled because fcntl hangs on the Sun
  46. X     and it isn't supported properly across NFS anyway.  */
  47. X  #ifdef LOCKS
  48. X  /* You might need to compile with -I/usr/include/sys if your fcntl.h
  49. X     isn't in /usr/include (which is where it should be according to POSIX).  */
  50. X  #include <fcntl.h>
  51. X! #endif
  52. X  
  53. X  /* This structure is used internally to represent the info
  54. X     on a member of an archive.  This is to make it easier to change format.  */
  55. X--- 71,118 ----
  56. X  #define    bzero(s, size)            memset((s), 0, (size))
  57. X  #endif
  58. X  
  59. X! /* If LOCKS is defined, locking is enabled.  If LOCK_FLOCK is defined,
  60. X!    then BSD-style flock() is used.  Otherwise, fcntl() is used.  If
  61. X!    LOCKS is not defined, LOCK_FLOCK is irrelevant.
  62. X! 
  63. X!    Locking is normally disabled because fcntl hangs on the Sun
  64. X     and it isn't supported properly across NFS anyway.  */
  65. X+ 
  66. X  #ifdef LOCKS
  67. X+ 
  68. X+ /* This flag tells whether the archive was opened read-only or
  69. X+    read-write.  It is used for a sanity check before trying to write a
  70. X+    new archive.  It is also temporarily as a workaround for a Sprite
  71. X+    bug that requires flock() to pass in the type of lock that is being
  72. X+    unlocked.  */
  73. X+ 
  74. X+ int open_flags;                /* O_RDONLY or O_RDWRITE */
  75. X+ 
  76. X+ #ifndef LOCK_FLOCK
  77. X  /* You might need to compile with -I/usr/include/sys if your fcntl.h
  78. X     isn't in /usr/include (which is where it should be according to POSIX).  */
  79. X  #include <fcntl.h>
  80. X! #endif /* LOCK_FLOCK */
  81. X! 
  82. X! void lock_a_file (), unlock_a_file ();
  83. X! #endif /* LOCKS */
  84. X! 
  85. X! /* This structure represents member names.  It is here to simplify 
  86. X!    dealing with different truncation schemes and with names that the
  87. X!    user specifies as paths.  Operations deal with the `stored' name,
  88. X!    except we maintain a mapping to the name the user gave for
  89. X!    reading/writing the member.   If the user didn't specify a name
  90. X!    that matches the `stored' name, the `given' name is NULL.  For
  91. X!    names provided by the user, the `stored' name is computed
  92. X!    immediately, so all member_name objects should have a non-null
  93. X!    `stored' name.  */
  94. X! 
  95. X! struct member_name {
  96. X!   char *given;                /* name given by the user */
  97. X!   char *stored;                /* name as stored in the ar header */
  98. X! };
  99. X! 
  100. X! #define Empty_Name(name)    ((name)->stored == NULL)
  101. X  
  102. X  /* This structure is used internally to represent the info
  103. X     on a member of an archive.  This is to make it easier to change format.  */
  104. X***************
  105. X*** 77,84 ****
  106. X  
  107. X  struct member_desc
  108. X    {
  109. X!     /* Name of member.  */
  110. X!     char *name;
  111. X  
  112. X      /* The following fields are stored in the member header as decimal or octal
  113. X         numerals, but in this structure they are stored as machine numbers.  */
  114. X--- 119,128 ----
  115. X  
  116. X  struct member_desc
  117. X    {
  118. X!     /* `given' will be zero if the user didn't specifically name this
  119. X!        member.  The name will be empty if this member is marked for
  120. X!        deletion.  */
  121. X!     struct member_name name;
  122. X  
  123. X      /* The following fields are stored in the member header as decimal or octal
  124. X         numerals, but in this structure they are stored as machine numbers.  */
  125. X***************
  126. X*** 112,121 ****
  127. X      unsigned long int offset;
  128. X    };
  129. X  
  130. X! /* Nonzero means it's the name of an existing member;
  131. X     position new or moved files with respect to this one.  */
  132. X  
  133. X! char *posname;
  134. X  
  135. X  
  136. X  /* How to use `posname':
  137. X--- 156,165 ----
  138. X      unsigned long int offset;
  139. X    };
  140. X  
  141. X! /* Nonzero means that it's the name of an existing member;
  142. X     position new or moved files with respect to this one.  */
  143. X  
  144. X! struct member_name *posname;
  145. X  
  146. X  
  147. X  /* How to use `posname':
  148. X***************
  149. X*** 158,173 ****
  150. X  
  151. X  char *archive;
  152. X  
  153. X! /* Descriptor on which we have locked the original archive file,
  154. X!    or -1 if this has not been done.  */
  155. X  
  156. X! int lock_indesc;
  157. X  
  158. X! /* Pointer to tail of `argv', at first subfile name argument,
  159. X!  or zero if no such were specified.  */
  160. X  
  161. X! char **files;
  162. X  
  163. X  /* Nonzero means write a __.SYMDEF member into the modified archive.  */
  164. X  
  165. X  int symdef_flag;
  166. X--- 202,230 ----
  167. X  
  168. X  char *archive;
  169. X  
  170. X! /* Descriptor for the archive file.  This descriptor is used for
  171. X!    locking the archive.  -1 if the archive is not yet opened.  */
  172. X  
  173. X! int arcfd;
  174. X  
  175. X! /* File pointer for the archive, used only for reading the archive.  0 
  176. X!    if the archive hasn't been opened yet.  */
  177. X! 
  178. X! FILE *arcstream;
  179. X! 
  180. X! /* (Pointer to) an array of file names specified by the user.  The 
  181. X!    last element is a dummy, with an "empty" name.  The remaining
  182. X!    elements have both `given' and `header' filled in.  Zero if the
  183. X!    user didn't specify any file names.  */
  184. X! 
  185. X! struct member_name *file_args;
  186. X! 
  187. X! /* *** Lots of globals related to the __.SYMDEF member.***  */
  188. X  
  189. X! /* Name "__.SYMDEF", converted to "member_name" form. */
  190. X  
  191. X+ struct member_name symdef_name;
  192. X+ 
  193. X  /* Nonzero means write a __.SYMDEF member into the modified archive.  */
  194. X  
  195. X  int symdef_flag;
  196. X***************
  197. X*** 212,217 ****
  198. X--- 269,287 ----
  199. X  
  200. X  unsigned long int new_strings_size;
  201. X  
  202. X+ /* ***End of __.SYMDEF globals.*** */
  203. X+ 
  204. X+ /* Controls the way in which long names are truncated.  If non-zero,
  205. X+    SomeVeryLongName.o is converted to SomeVeryLongN.o.  Otherwise, it
  206. X+    is converted to SomeVeryLongNam (which is compatible with the BSD
  207. X+    ar).  */
  208. X+ 
  209. X+ #ifndef GNU_TRUNCATION
  210. X+ #define GNU_TRUNCATION    1
  211. X+ #endif
  212. X+ 
  213. X+ int gnu_truncation = GNU_TRUNCATION;
  214. X+ 
  215. X  /* An archive map is a chain of these structures.
  216. X    Each structure describes one member of the archive.
  217. X    The chain is in the same order as the members are.  */
  218. X***************
  219. X*** 249,259 ****
  220. X--- 319,342 ----
  221. X  void two_operations ();
  222. X  void usage (), fatal (), error (), error_with_file ();
  223. X  void perror_with_name (), pfatal_with_name ();
  224. X+ void open_archive ();
  225. X  void write_archive ();
  226. X  void touch_symdef_member ();
  227. X  void update_symdefs ();
  228. X  void delete_members (), move_members (), replace_members ();
  229. X  void quick_append ();
  230. X+ void init_elt (), mark_as_deleted ();
  231. X+ int marked_for_deletion ();
  232. X+ int name_match ();
  233. X+ void init_name (), free_name_strings ();
  234. X+ int move_in_map ();
  235. X+ int filter_symbols ();
  236. X+ char *user_to_header ();
  237. X+ struct member_name *make_file_args ();
  238. X+ void verify_is_archive ();
  239. X+ #if DEBUG
  240. X+ void verify_symdefs ();
  241. X+ #endif
  242. X  
  243. X  /* Output BYTES of data at BUF to the descriptor DESC.
  244. X     FILE is the name of the file (for error messages).  */
  245. X***************
  246. X*** 291,302 ****
  247. X    posname = 0;
  248. X    postype = POS_DEFAULT;
  249. X    preserve_dates = 0;
  250. X    symdef_flag = 0;
  251. X    symdef_exists = 0;
  252. X    ignore_symdef = 0;
  253. X    symdef_mapelt = 0;
  254. X!   files = 0;
  255. X!   lock_indesc = -1;
  256. X  
  257. X    if (argc < 2)
  258. X      usage ("too few command arguments", 0);
  259. X--- 374,387 ----
  260. X    posname = 0;
  261. X    postype = POS_DEFAULT;
  262. X    preserve_dates = 0;
  263. X+   init_name (&symdef_name, "__.SYMDEF");
  264. X    symdef_flag = 0;
  265. X    symdef_exists = 0;
  266. X    ignore_symdef = 0;
  267. X    symdef_mapelt = 0;
  268. X!   file_args = 0;
  269. X!   arcfd = -1;
  270. X!   arcstream = 0;
  271. X  
  272. X    if (argc < 2)
  273. X      usage ("too few command arguments", 0);
  274. X***************
  275. X*** 359,365 ****
  276. X          break;
  277. X  
  278. X        case 'r':
  279. X!         if (operation)
  280. X            two_operations ();
  281. X          operation = REPLACE;
  282. X          break;
  283. X--- 444,450 ----
  284. X          break;
  285. X  
  286. X        case 'r':
  287. X!         if (operation && operation != REPLACE)
  288. X            two_operations ();
  289. X          operation = REPLACE;
  290. X          break;
  291. X***************
  292. X*** 375,380 ****
  293. X--- 460,467 ----
  294. X          break;
  295. X  
  296. X        case 'u':
  297. X+         if (operation && operation != REPLACE)
  298. X+           two_operations ();
  299. X          operation = REPLACE;
  300. X          newer_only = 1;
  301. X          break;
  302. X***************
  303. X*** 402,414 ****
  304. X    i = 2;
  305. X  
  306. X    if (postype != POS_DEFAULT)
  307. X!     posname = argv[i++];
  308. X  
  309. X    archive = argv[i++];
  310. X  
  311. X    if (i < argc)
  312. X      {
  313. X!       files = &argv[i];
  314. X        while (i < argc)
  315. X      if (!strcmp (argv[i++], "__.SYMDEF"))
  316. X        {
  317. X--- 489,501 ----
  318. X    i = 2;
  319. X  
  320. X    if (postype != POS_DEFAULT)
  321. X!     posname = make_file_args(&argv[i++], 1);
  322. X  
  323. X    archive = argv[i++];
  324. X  
  325. X    if (i < argc)
  326. X      {
  327. X!       file_args = make_file_args(&argv[i], argc - i);
  328. X        while (i < argc)
  329. X      if (!strcmp (argv[i++], "__.SYMDEF"))
  330. X        {
  331. X***************
  332. X*** 432,453 ****
  333. X      break;
  334. X  
  335. X      case DELETE:
  336. X!     if (files != 0)
  337. X        delete_members ();
  338. X      break;
  339. X  
  340. X      case MOVE:
  341. X!     if (files != 0)
  342. X        move_members ();
  343. X      break;
  344. X  
  345. X      case REPLACE:
  346. X!     if (files != 0 || symdef_flag)
  347. X        replace_members ();
  348. X      break;
  349. X  
  350. X      case QUICK_APPEND:
  351. X!     if (files != 0)
  352. X        quick_append ();
  353. X      break;
  354. X  
  355. X--- 519,540 ----
  356. X      break;
  357. X  
  358. X      case DELETE:
  359. X!     if (file_args != 0)
  360. X        delete_members ();
  361. X      break;
  362. X  
  363. X      case MOVE:
  364. X!     if (file_args != 0)
  365. X        move_members ();
  366. X      break;
  367. X  
  368. X      case REPLACE:
  369. X!     if (file_args != 0 || symdef_flag)
  370. X        replace_members ();
  371. X      break;
  372. X  
  373. X      case QUICK_APPEND:
  374. X!     if (file_args != 0)
  375. X        quick_append ();
  376. X      break;
  377. X  
  378. X***************
  379. X*** 465,476 ****
  380. X    usage ("two different operation switches specified", 0);
  381. X  }
  382. X  
  383. X  void
  384. X  scan (function, crflag)
  385. X       void (*function) ();
  386. X       int crflag;
  387. X  {
  388. X!   FILE *arcstream = fopen (archive, "r");
  389. X  
  390. X    if (arcstream == 0 && crflag)
  391. X      /* Creation-warning, if desired, will happen later.  */
  392. X--- 552,566 ----
  393. X    usage ("two different operation switches specified", 0);
  394. X  }
  395. X  
  396. X+ /* Apply the given function to all members in the archive.  */
  397. X+ 
  398. X  void
  399. X  scan (function, crflag)
  400. X       void (*function) ();
  401. X       int crflag;
  402. X  {
  403. X!   if (arcstream == 0)
  404. X!     open_archive (O_RDONLY);
  405. X  
  406. X    if (arcstream == 0 && crflag)
  407. X      /* Creation-warning, if desired, will happen later.  */
  408. X***************
  409. X*** 477,492 ****
  410. X      return;
  411. X  
  412. X    if (arcstream == 0)
  413. X!     {
  414. X!       perror_with_name (archive);
  415. X!       exit (1);
  416. X!     }
  417. X!   {
  418. X!     char buf[SARMAG];
  419. X!     int nread = fread (buf, 1, SARMAG, arcstream);
  420. X!     if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG))
  421. X!       fatal ("file %s not a valid archive", archive);
  422. X!   }
  423. X  
  424. X    /* Now find the members one by one.  */
  425. X    {
  426. X--- 567,574 ----
  427. X      return;
  428. X  
  429. X    if (arcstream == 0)
  430. X!     pfatal_with_name (archive);
  431. X!   verify_is_archive (arcfd);
  432. X  
  433. X    /* Now find the members one by one.  */
  434. X    {
  435. X***************
  436. X*** 510,515 ****
  437. X--- 592,599 ----
  438. X          || bcmp (member_header.ar_fmag, ARFMAG, 2))
  439. X        fatal ("file %s not a valid archive", archive);
  440. X      bcopy (member_header.ar_name, name, sizeof member_header.ar_name);
  441. X+ 
  442. X+     /* remove trailing blanks */
  443. X      {
  444. X        char *p = name + sizeof member_header.ar_name;
  445. X        *p = '\0';
  446. X***************
  447. X*** 516,522 ****
  448. X        while (p > name && *--p == ' ')
  449. X          *p = '\0';
  450. X      }
  451. X!     member_desc.name = name;
  452. X      sscanf (member_header.ar_mode, "%o", &member_desc.mode);
  453. X      member_desc.date = atoi (member_header.ar_date);
  454. X      member_desc.size = atoi (member_header.ar_size);
  455. X--- 600,611 ----
  456. X        while (p > name && *--p == ' ')
  457. X          *p = '\0';
  458. X      }
  459. X! 
  460. X!     /* Make a safe copy of the name, so that `function' can just 
  461. X!        make a copy of `member_desc'.  */
  462. X!     member_desc.name.stored = concat (name, "", "");
  463. X!     member_desc.name.given = NULL;
  464. X! 
  465. X      sscanf (member_header.ar_mode, "%o", &member_desc.mode);
  466. X      member_desc.date = atoi (member_header.ar_date);
  467. X      member_desc.size = atoi (member_header.ar_size);
  468. X***************
  469. X*** 540,548 ****
  470. X        ++member_offset;
  471. X        }
  472. X    }
  473. X- 
  474. X-   
  475. X-   fclose (arcstream);
  476. X  }
  477. X  
  478. X  void print_modes ();
  479. X--- 629,634 ----
  480. X***************
  481. X*** 554,560 ****
  482. X    char *timestring;
  483. X    if (!verbose)
  484. X      {
  485. X!       puts (member.name);
  486. X        return;
  487. X      }
  488. X    print_modes (member.mode);
  489. X--- 640,646 ----
  490. X    char *timestring;
  491. X    if (!verbose)
  492. X      {
  493. X!       puts (member.name.stored);
  494. X        return;
  495. X      }
  496. X    print_modes (member.mode);
  497. X***************
  498. X*** 562,568 ****
  499. X    printf (" %2d/%2d %6d %12.12s %4.4s %s\n",
  500. X        member.uid, member.gid,
  501. X        member.size, timestring + 4, timestring + 20,
  502. X!       member.name);
  503. X  }
  504. X  
  505. X  void
  506. X--- 648,654 ----
  507. X    printf (" %2d/%2d %6d %12.12s %4.4s %s\n",
  508. X        member.uid, member.gid,
  509. X        member.size, timestring + 4, timestring + 20,
  510. X!       member.name.stored);
  511. X  }
  512. X  
  513. X  void
  514. X***************
  515. X*** 589,605 ****
  516. X  {
  517. X    int ncopied = 0;
  518. X    FILE *ostream;
  519. X  
  520. X    fseek (istream, member.data_offset, 0);
  521. X!   ostream = fopen (member.name, "w");
  522. X    if (!ostream)
  523. X      {
  524. X!       perror_with_name (member.name);
  525. X        return;
  526. X      }
  527. X  
  528. X    if (verbose)
  529. X!     printf ("x - %s\n", member.name);
  530. X  
  531. X    while (ncopied < member.size)
  532. X      {
  533. X--- 675,693 ----
  534. X  {
  535. X    int ncopied = 0;
  536. X    FILE *ostream;
  537. X+   char *filename;            /* name to store file into */
  538. X  
  539. X    fseek (istream, member.data_offset, 0);
  540. X!   filename = (member.name.given ? member.name.given : member.name.stored);
  541. X!   ostream = fopen (filename, "w");
  542. X    if (!ostream)
  543. X      {
  544. X!       perror_with_name (filename);
  545. X        return;
  546. X      }
  547. X  
  548. X    if (verbose)
  549. X!     printf ("x - %s\n", filename);
  550. X  
  551. X    while (ncopied < member.size)
  552. X      {
  553. X***************
  554. X*** 615,626 ****
  555. X      }
  556. X  
  557. X  #ifdef USG
  558. X!   chmod (member.name, member.mode);
  559. X  #else
  560. X    fchmod (fileno (ostream), member.mode);
  561. X  #endif
  562. X    if (ferror (ostream) || fclose (ostream) != 0)
  563. X!     error ("%s: I/O error", member.name);
  564. X  
  565. X    if (preserve_dates)
  566. X      {
  567. X--- 703,714 ----
  568. X      }
  569. X  
  570. X  #ifdef USG
  571. X!   chmod (filename, member.mode);
  572. X  #else
  573. X    fchmod (fileno (ostream), member.mode);
  574. X  #endif
  575. X    if (ferror (ostream) || fclose (ostream) != 0)
  576. X!     error ("%s: I/O error", filename);
  577. X  
  578. X    if (preserve_dates)
  579. X      {
  580. X***************
  581. X*** 628,634 ****
  582. X        long tv[2];
  583. X        tv[0] = member.date;
  584. X        tv[1] = member.date;
  585. X!       utime (member.name, tv);
  586. X  #else
  587. X        struct timeval tv[2];
  588. X        tv[0].tv_sec = member.date;
  589. X--- 716,722 ----
  590. X        long tv[2];
  591. X        tv[0] = member.date;
  592. X        tv[1] = member.date;
  593. X!       utime (filename, tv);
  594. X  #else
  595. X        struct timeval tv[2];
  596. X        tv[0].tv_sec = member.date;
  597. X***************
  598. X*** 635,641 ****
  599. X        tv[0].tv_usec = 0;
  600. X        tv[1].tv_sec = member.date;
  601. X        tv[1].tv_usec = 0;
  602. X!       utimes (member.name, tv);
  603. X  #endif
  604. X      }
  605. X  }
  606. X--- 723,729 ----
  607. X        tv[0].tv_usec = 0;
  608. X        tv[1].tv_sec = member.date;
  609. X        tv[1].tv_usec = 0;
  610. X!       utimes (filename, tv);
  611. X  #endif
  612. X      }
  613. X  }
  614. X***************
  615. X*** 650,656 ****
  616. X    fseek (istream, member.data_offset, 0);
  617. X  
  618. X    if (verbose)
  619. X!   printf ("\n<member %s>\n\n", member.name);
  620. X  
  621. X    while (ncopied < member.size)
  622. X      {
  623. X--- 738,744 ----
  624. X    fseek (istream, member.data_offset, 0);
  625. X  
  626. X    if (verbose)
  627. X!     printf ("\n<member %s>\n\n", member.name.stored);
  628. X  
  629. X    while (ncopied < member.size)
  630. X      {
  631. X***************
  632. X*** 690,697 ****
  633. X       struct member_desc member;
  634. X  {
  635. X    struct mapelt *mapelt = (struct mapelt *) xmalloc (sizeof (struct mapelt));
  636. X    mapelt->info = member;
  637. X-   mapelt->info.name = concat (mapelt->info.name, "", "");
  638. X    maplast->next = mapelt;
  639. X    mapelt->next = 0;
  640. X    maplast = mapelt;
  641. X--- 778,785 ----
  642. X       struct member_desc member;
  643. X  {
  644. X    struct mapelt *mapelt = (struct mapelt *) xmalloc (sizeof (struct mapelt));
  645. X+ 
  646. X    mapelt->info = member;
  647. X    maplast->next = mapelt;
  648. X    mapelt->next = 0;
  649. X    maplast = mapelt;
  650. X***************
  651. X*** 721,756 ****
  652. X    return 0;
  653. X  }
  654. X  
  655. X! /* Return the element of the specified map which has the specified name.  */
  656. X  
  657. X  struct mapelt *
  658. X  find_mapelt_noerror (map, name)
  659. X       struct mapelt *map;
  660. X!      register char *name;
  661. X  {
  662. X    register struct mapelt *tail;
  663. X-   unsigned int len = strlen (name);
  664. X-   int dot_o = name[len - 2] == '.' && name[len - 1] == 'o';
  665. X  
  666. X    for (tail = map; tail != 0; tail = tail->next)
  667. X      {
  668. X!       if (tail->info.name == 0)
  669. X      continue;
  670. X!       if (!strncmp (tail->info.name, name, 13))
  671. X!     {
  672. X!       unsigned int eltlen = strlen (tail->info.name);
  673. X!       if (len <= 13 || eltlen <= 13)
  674. X!         return tail;
  675. X!       else
  676. X!         {
  677. X!           char *p = tail->info.name + 13;
  678. X!           if (dot_o && p[0] == '.' && p[1] == 'o' && p[2] == '\0')
  679. X!         return tail;
  680. X!           else if (!strncmp (p, name + 13,
  681. X!                  (len > eltlen ? len : eltlen) - 13))
  682. X!         return tail;
  683. X!         }
  684. X!     }
  685. X      }
  686. X  
  687. X    return 0;
  688. X--- 809,832 ----
  689. X    return 0;
  690. X  }
  691. X  
  692. X! /* Return the element of the specified map which has the specified 
  693. X!    name.  Possible side effect: if NAME or the matching element has a
  694. X!    known `given' (user) name, that name is propagated so that both
  695. X!    NAME and the matching element have it.  */
  696. X  
  697. X  struct mapelt *
  698. X  find_mapelt_noerror (map, name)
  699. X       struct mapelt *map;
  700. X!      struct member_name *name;
  701. X  {
  702. X    register struct mapelt *tail;
  703. X  
  704. X    for (tail = map; tail != 0; tail = tail->next)
  705. X      {
  706. X!       if (marked_for_deletion (tail))
  707. X      continue;
  708. X!       if (name_match (&tail->info.name, name))
  709. X!     return tail;
  710. X      }
  711. X  
  712. X    return 0;
  713. X***************
  714. X*** 759,878 ****
  715. X  struct mapelt *
  716. X  find_mapelt (map, name)
  717. X       struct mapelt *map;
  718. X!      char *name;
  719. X  {
  720. X    register struct mapelt *found = find_mapelt_noerror (map, name);
  721. X    if (found == 0)
  722. X!     error ("no member named `%s'", name);
  723. X    return found;
  724. X  }
  725. X  
  726. X! /* Before looking at the archive, if we are going to update it
  727. X!    based on looking at its current contents, make an exclusive lock on it.
  728. X!    The lock is released when `write_archive' is called.  */
  729. X  
  730. X  void
  731. X! lock_for_update ()
  732. X! {
  733. X!   /* Open the existing archive file; if that fails, create an empty one.  */
  734. X! 
  735. X!   lock_indesc = open (archive, O_RDWR, 0);
  736. X  
  737. X!   if (lock_indesc < 0)
  738. X!     {
  739. X!       int outdesc;
  740. X  
  741. X        if (!silent_create)
  742. X      printf ("Creating archive file `%s'\n", archive);
  743. X!       outdesc = open (archive, O_WRONLY | O_APPEND | O_CREAT, 0666);
  744. X!       if (outdesc < 0)
  745. X!     pfatal_with_name (archive);
  746. X!       mywrite (outdesc, ARMAG, SARMAG, archive);
  747. X!       close (outdesc);
  748. X  
  749. X!       /* Now we had better be able to open for update!  */
  750. X  
  751. X!       lock_indesc = open (archive, O_RDWR, 0);
  752. X!       if (lock_indesc < 0)
  753. X!     pfatal_with_name (archive);
  754. X!     }
  755. X  
  756. X! #ifdef LOCKS
  757. X!   /* Lock the old file so that it won't be updated by two programs at once.
  758. X!      This uses the fcntl locking facility found on Sun systems
  759. X!      which is also in POSIX.  (Perhaps it comes from sysV.)
  760. X  
  761. X!      Note that merely reading an archive does not require a lock,
  762. X!      because we use `rename' to update the whole file atomically.  */
  763. X  
  764. X    {
  765. X      struct flock lock;
  766. X  
  767. X!     lock.l_type = F_WRLCK;
  768. X      lock.l_whence = 0;
  769. X      lock.l_start = 0;
  770. X      lock.l_len = 0;
  771. X  
  772. X!     while (1)
  773. X!       {
  774. X!     int value = fcntl (lock_indesc, F_SETLKW, &lock);
  775. X!     if (value >= 0)
  776. X!       break;
  777. X!     else if (errno == EINTR)
  778. X!       continue;
  779. X!     else
  780. X!       pfatal_with_name ("locking archive");
  781. X!       }
  782. X    }
  783. X! #endif
  784. X  }
  785. X  
  786. X  /* Unlock archive and close the file descriptor.  */
  787. X  
  788. X  void
  789. X  close_archive ()
  790. X  {
  791. X! #ifdef LOCKS
  792. X!   {
  793. X!     struct flock lock;
  794. X! 
  795. X!     /* Unlock the old archive.  */
  796. X! 
  797. X!     lock.l_type = F_UNLCK;
  798. X!     lock.l_whence = 0;
  799. X!     lock.l_start = 0;
  800. X!     lock.l_len = 0;
  801. X! 
  802. X!     fcntl (lock_indesc, F_SETLK, &lock);
  803. X!   }
  804. X  #endif
  805. X  
  806. X!   /* Close the archive.  If we renamed a new one, the old one disappears.  */
  807. X!   close (lock_indesc);
  808. X  }
  809. X  
  810. X  /* Write a new archive file from a given map.  */
  811. X  /* When a map is used as the pattern for a new archive,
  812. X!  each element represents one member to put in it, and
  813. X!  the order of elements controls the order of writing.
  814. X! 
  815. X!  Ordinarily, the element describes a member of the old
  816. X!  archive, to be copied into the new one.
  817. X! 
  818. X!  If the `offset' field of the element's info is 0,
  819. X!  then the element describes a file to be copied into the
  820. X!  new archive.  The `name' field is the file's name.
  821. X! 
  822. X!  If the `name' field of an element is 0, the element is ignored.
  823. X!  This makes it easy to specify deletion of archive members.
  824. X  
  825. X!  Every operation that will eventually call `write_archive'
  826. X!  should call `lock_for_update' before beginning
  827. X!  to do any I/O on the archive file.
  828. X  */
  829. X  
  830. X  char *make_tempname ();
  831. X  void copy_out_member ();
  832. X  
  833. X  void
  834. X  write_archive (map, appendflag)
  835. X--- 835,1093 ----
  836. X  struct mapelt *
  837. X  find_mapelt (map, name)
  838. X       struct mapelt *map;
  839. X!      struct member_name *name;
  840. X  {
  841. X    register struct mapelt *found = find_mapelt_noerror (map, name);
  842. X    if (found == 0)
  843. X!     error ("no member named `%s'", name->stored);
  844. X    return found;
  845. X  }
  846. X  
  847. X! /* Open the archive, either read-only or read-write, using the global
  848. X!    name "archive".  The archive is locked at this time to protect
  849. X!    against a concurrent writer.  This lock will be released when the
  850. X!    archive is closed.  This routine should only be called once--no
  851. X!    upgrading of access from read-only to read-write is allowed.
  852. X! 
  853. X!    Side effects:
  854. X!    - If opening read-write and the archive doesn't exist, create it.
  855. X!    - arcfd and arctream are set to mean the opened archive.  If the
  856. X!      archive doesn't exist and can't be created, they are left as
  857. X!      meaning "unopened".  */
  858. X! 
  859. X! void
  860. X! open_archive (how)
  861. X!      int how;                /* O_RDONLY or O_RDWR */
  862. X! {
  863. X!   void open_for_reading (), open_for_update ();
  864. X!   if (arcfd != -1 || arcstream != 0)
  865. X!     fatal ("opening archive twice");
  866. X! 
  867. X!   switch (how)
  868. X!     {
  869. X!     case O_RDONLY:
  870. X!       open_for_reading ();
  871. X!       break;
  872. X!     case O_RDWR:
  873. X!       open_for_update ();
  874. X!       break;
  875. X!     default:
  876. X!       fatal ("bogus flag passed to open_archive");
  877. X!     }
  878. X! }
  879. X! 
  880. X! /* Open the archive for read-only access.  If the archive doesn't
  881. X!    exist, just quit.  */
  882. X! 
  883. X! void
  884. X! open_for_reading ()
  885. X! {
  886. X!   arcfd = open (archive, O_RDONLY, 0);
  887. X!   if (arcfd < 0 && errno != ENOENT)
  888. X!     pfatal_with_name (archive);
  889. X!   if (arcfd < 0)
  890. X!     return;
  891. X! 
  892. X!   lock_a_file (arcfd, O_RDONLY);
  893. X  
  894. X+   arcstream = fdopen (arcfd, "r");
  895. X+   if (arcstream == 0)
  896. X+     fatal ("can't make stream for archive");
  897. X+ }
  898. X+ 
  899. X+ /* Open the archive for read-write access.  If it doesn't exist,
  900. X+    create it.  The order of creates and opens and locks is to keep
  901. X+    competing ar's (spawned by pmake) from tripping on each other.  */
  902. X+ 
  903. X  void
  904. X! open_for_update ()
  905. X! {
  906. X!   struct stat statbuf;
  907. X  
  908. X!   /* Assume that the archive doesn't exist, and try to create it.  If 
  909. X!      it does exist, just open it normally.  */
  910. X!   arcfd = open (archive, O_RDWR | O_CREAT | O_EXCL, 0666);
  911. X!   if (arcfd < 0 && errno != EEXIST)
  912. X!     pfatal_with_name (archive);
  913. X  
  914. X+   if (arcfd >= 0)
  915. X+     {
  916. X        if (!silent_create)
  917. X      printf ("Creating archive file `%s'\n", archive);
  918. X!     }
  919. X!   else
  920. X!     arcfd = open (archive, O_RDWR, 0);
  921. X  
  922. X!   /* If the file suddenly doesn't exist, punt.  Some user must have
  923. X!      manually deleted the file.  */
  924. X!   if (arcfd < 0)
  925. X!     pfatal_with_name (archive);
  926. X! 
  927. X!   lock_a_file (arcfd, O_RDWR);
  928. X! 
  929. X!   /* Whew.  Now that we've got the file and it's locked, check whether
  930. X!      it's really an archive or just an empty shell, created either by
  931. X!      us or by a competing ar.  */
  932. X! 
  933. X!   fstat (arcfd, &statbuf);
  934. X!   if (statbuf.st_size == 0)
  935. X!     mywrite (arcfd, ARMAG, SARMAG, archive);
  936. X!   else
  937. X!     verify_is_archive (arcfd);
  938. X  
  939. X!   arcstream = fdopen (arcfd, "r+");
  940. X!   if (arcstream == 0)
  941. X!     fatal ("can't create stream for archive");
  942. X! }
  943. X  
  944. X! #ifndef LOCKS
  945. X  
  946. X! void
  947. X! lock_a_file (fd, how)
  948. X!      int fd, how;
  949. X! {
  950. X! }
  951. X! 
  952. X! void
  953. X! unlock_a_file (fd)
  954. X!      int fd;
  955. X! {
  956. X! }
  957. X! 
  958. X! #else /* LOCKS */
  959. X! 
  960. X! /* Lock the old file so that it won't be written while there are
  961. X!    readers or another writer.
  962. X!    Non-sprite systems use the fcntl locking facility found on Sun
  963. X!    systems, which is also in POSIX.  (Perhaps it comes from sysV.)  */
  964. X! 
  965. X! #ifndef LOCK_FLOCK
  966. X! 
  967. X! void
  968. X! lock_a_file (fd, how)
  969. X!      int fd;
  970. X!      int how;                /* read/write flag */
  971. X! {
  972. X!   struct flock lock;
  973. X! 
  974. X!   lock.l_type = (how == O_RDONLY ? F_RDLCK : F_WRLCK);
  975. X!   lock.l_whence = 0;
  976. X!   lock.l_start = 0;
  977. X!   lock.l_len = 0;
  978. X! 
  979. X!   while (1)
  980. X!     {
  981. X!       int value = fcntl (fd, F_SETLKW, &lock);
  982. X!       if (value >= 0)
  983. X!     break;
  984. X!       else if (errno == EINTR)
  985. X!     continue;
  986. X!       else
  987. X!     pfatal_with_name ("locking archive");
  988. X!     }
  989. X! }
  990. X  
  991. X+ void
  992. X+ unlock_a_file (fd)
  993. X+      int fd;
  994. X    {
  995. X      struct flock lock;
  996. X  
  997. X!     /* Unlock the old archive.  */
  998. X! 
  999. X!     lock.l_type = F_UNLCK;
  1000. X      lock.l_whence = 0;
  1001. X      lock.l_start = 0;
  1002. X      lock.l_len = 0;
  1003. X  
  1004. X!     fcntl (fd, F_SETLK, &lock);
  1005. X    }
  1006. X! 
  1007. X! #else /* LOCK_FLOCK */
  1008. X! 
  1009. X! void
  1010. X! lock_a_file (fd, how)
  1011. X!      int fd;
  1012. X!      int how;                /* read/write flag */
  1013. X! {
  1014. X!   int lock_type = (how == O_RDONLY ? LOCK_SH : LOCK_EX);
  1015. X! 
  1016. X!   open_flags = how;
  1017. X!   if (flock (fd, lock_type) < 0)
  1018. X!     pfatal_with_name (archive);
  1019. X! }
  1020. X! 
  1021. X! /* Putting lock_flags in the flock() call is a workaround for a bug in 
  1022. X!    Sprite's flock() emulation.  -mdk 19-Oct-90 */
  1023. X! 
  1024. X! void
  1025. X! unlock_a_file (fd)
  1026. X!      int fd;
  1027. X! {
  1028. X!   int lock_type = (open_flags == O_RDONLY ? LOCK_SH : LOCK_EX);
  1029. X! 
  1030. X!   if (flock (fd, LOCK_UN | lock_type) < 0)
  1031. X!     pfatal_with_name (archive);
  1032. X  }
  1033. X  
  1034. X+ #endif /* LOCK_FLOCK */
  1035. X+ #endif /* LOCKS */
  1036. X+ 
  1037. X  /* Unlock archive and close the file descriptor.  */
  1038. X  
  1039. X  void
  1040. X  close_archive ()
  1041. X  {
  1042. X! #ifndef USG
  1043. X!   fsync (arcfd);
  1044. X  #endif
  1045. X+   unlock_a_file (arcfd);
  1046. X+   if (close (arcfd) < 0)
  1047. X+     {
  1048. X+       perror_with_name (archive);
  1049. X+       exit (1);
  1050. X+     }
  1051. X+ }
  1052. X+ 
  1053. X+ /* Ensure that the given file is an archive.  Side effect: repositions
  1054. X+    the archive.  After calling this routine, you should do a seek.  */
  1055. X  
  1056. X! void
  1057. X! verify_is_archive (fd)
  1058. X!      int fd;
  1059. X! {
  1060. X!   char buf[SARMAG];
  1061. X!   int nread;
  1062. X! 
  1063. X!   lseek (fd, 0, L_SET);
  1064. X!   nread = read (fd, buf, sizeof (buf));
  1065. X!   if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG) != 0)
  1066. X!     fatal ("file %s not a valid archive", archive);
  1067. X  }
  1068. X  
  1069. X  /* Write a new archive file from a given map.  */
  1070. X  /* When a map is used as the pattern for a new archive,
  1071. X!    each element represents one member to put in it, and
  1072. X!    the order of elements controls the order of writing.
  1073. X!   
  1074. X!    Ordinarily, the element describes a member of the old
  1075. X!    archive, to be copied into the new one.
  1076. X!   
  1077. X!    If, however, the `offset' field of the element's info is 0,
  1078. X!    then the element describes a file to be copied into the
  1079. X!    new archive.
  1080. X  
  1081. X!    The archive is updated by writing a new file and then copying the
  1082. X!    new file onto the old one.  We don't use rename, because if some
  1083. X!    other "ar" has the archive open and is waiting to obtain the lock,
  1084. X!    it would end up with the old file, not the new one.  There can
  1085. X!    never be two ar's writing the new file simultaneously, because of
  1086. X!    the lock on the archive.
  1087. X  */
  1088. X  
  1089. X  char *make_tempname ();
  1090. X  void copy_out_member ();
  1091. X+ void copy_file ();
  1092. X  
  1093. X  void
  1094. X  write_archive (map, appendflag)
  1095. X***************
  1096. X*** 880,900 ****
  1097. X       int appendflag;
  1098. X  {
  1099. X    char *tempname = make_tempname (archive);
  1100. X!   int indesc = lock_indesc;
  1101. X    int outdesc;
  1102. X    char *outname;
  1103. X    struct mapelt *tail;
  1104. X  
  1105. X    /* Now open the output.  */
  1106. X  
  1107. X    if (!appendflag)
  1108. X      {
  1109. X!       /* Updating an existing archive normally.
  1110. X!      Write output as TEMPNAME and rename at the end.
  1111. X!      There can never be two invocations trying to do this at once,
  1112. X!      because of the lock made on the old archive file.  */
  1113. X  
  1114. X!       outdesc = open (tempname, O_WRONLY | O_CREAT, 0666);
  1115. X        if (outdesc < 0)
  1116. X      pfatal_with_name (tempname);
  1117. X        outname = tempname;
  1118. X--- 1095,1117 ----
  1119. X       int appendflag;
  1120. X  {
  1121. X    char *tempname = make_tempname (archive);
  1122. X!   int indesc = arcfd;
  1123. X    int outdesc;
  1124. X    char *outname;
  1125. X    struct mapelt *tail;
  1126. X  
  1127. X+   /* Sanity check */
  1128. X+ 
  1129. X+   if (open_flags == O_RDONLY)
  1130. X+     fatal ("want to update archive after declaring read-only");
  1131. X+ 
  1132. X    /* Now open the output.  */
  1133. X  
  1134. X    if (!appendflag)
  1135. X      {
  1136. X!       /* Write the revised archive to TEMPNAME, then copy it back. */
  1137. X  
  1138. X!       outdesc = open (tempname, O_RDWR | O_CREAT, 0666);
  1139. X        if (outdesc < 0)
  1140. X      pfatal_with_name (tempname);
  1141. X        outname = tempname;
  1142. X***************
  1143. X*** 921,927 ****
  1144. X      {
  1145. X        struct mapelt *this = (struct mapelt *)
  1146. X          xmalloc (sizeof (struct mapelt));
  1147. X!       this->info.name = "__.SYMDEF";
  1148. X        this->info.offset = SARMAG;
  1149. X        this->info.data_offset = SARMAG + sizeof (struct ar_hdr);
  1150. X        this->info.new_offset = 0;
  1151. X--- 1138,1144 ----
  1152. X      {
  1153. X        struct mapelt *this = (struct mapelt *)
  1154. X          xmalloc (sizeof (struct mapelt));
  1155. X!       init_name (&this->info.name, "__.SYMDEF");
  1156. X        this->info.offset = SARMAG;
  1157. X        this->info.data_offset = SARMAG + sizeof (struct ar_hdr);
  1158. X        this->info.new_offset = 0;
  1159. X***************
  1160. X*** 947,954 ****
  1161. X  
  1162. X    for (tail = map; tail != 0; tail = tail->next)
  1163. X      {
  1164. X!       if ((symdef_flag || symdef_exists) && tail->info.name
  1165. X!       && !strcmp (tail->info.name, "__.SYMDEF")
  1166. X  #if 0
  1167. X        && tail->info.date==0
  1168. X  #endif
  1169. X--- 1164,1171 ----
  1170. X  
  1171. X    for (tail = map; tail != 0; tail = tail->next)
  1172. X      {
  1173. X!       if ((symdef_flag || symdef_exists) && !marked_for_deletion(tail)
  1174. X!       && name_match (&tail->info.name, &symdef_name)
  1175. X  #if 0
  1176. X        && tail->info.date==0
  1177. X  #endif
  1178. X***************
  1179. X*** 985,1028 ****
  1180. X    if (symdef_mapelt != 0)
  1181. X      touch_symdef_member (outdesc, outname);
  1182. X  
  1183. X!   /* Install the new output under the intended name.  */
  1184. X! 
  1185. X! #ifndef USG
  1186. X!   fsync (outdesc);
  1187. X! #endif
  1188. X    close (outdesc);
  1189. X- 
  1190. X    if (!appendflag)
  1191. X!     if (rename (tempname, archive))
  1192. X!       pfatal_with_name (tempname);
  1193. X  
  1194. X    close_archive ();
  1195. X  }
  1196. X  
  1197. X  void
  1198. X  header_from_map (header, mapelt)
  1199. X       struct ar_hdr *header;
  1200. X       struct mapelt *mapelt;
  1201. X  {
  1202. X-   unsigned int namelen;
  1203. X- 
  1204. X    /* Zero the header, then store in the data as text.  */
  1205. X    bzero ((char *) header, sizeof (*header));
  1206. X  
  1207. X!   strncpy (header->ar_name, mapelt->info.name, sizeof (header->ar_name));
  1208. X!   namelen = strlen (mapelt->info.name);
  1209. X!   if (namelen >= sizeof (header->ar_name))
  1210. X!     {
  1211. X!       if (mapelt->info.name[namelen - 2] == '.' &&
  1212. X!       mapelt->info.name[namelen - 1] == 'o')
  1213. X!     {
  1214. X!       header->ar_name[sizeof (header->ar_name) - 3] = '.';
  1215. X!       header->ar_name[sizeof (header->ar_name) - 2] = 'o';
  1216. X!     }
  1217. X!       header->ar_name[sizeof (header->ar_name) - 1] = '\0';
  1218. X!       error ("member name `%s' truncated to `%s'",
  1219. X!          mapelt->info.name, header->ar_name);
  1220. X!     }
  1221. X  
  1222. X    sprintf (header->ar_date, "%ld", mapelt->info.date);
  1223. X    sprintf (header->ar_size, "%d", mapelt->info.size);
  1224. X--- 1202,1254 ----
  1225. X    if (symdef_mapelt != 0)
  1226. X      touch_symdef_member (outdesc, outname);
  1227. X  
  1228. X!   if (!appendflag)
  1229. X!     copy_file (outdesc, tempname, arcfd, archive);
  1230. X    close (outdesc);
  1231. X    if (!appendflag)
  1232. X!     unlink (tempname);
  1233. X  
  1234. X    close_archive ();
  1235. X  }
  1236. X  
  1237. X+ /* Copy all of fromfd to tofd.  The file names are passed in for error
  1238. X+    reporting.  */
  1239. X+ 
  1240. X+ void
  1241. X+ copy_file (from_fd, from_name, to_fd, to_name)
  1242. X+      int from_fd, to_fd;
  1243. X+      char *from_name, *to_name;
  1244. X+ {
  1245. X+   char buf[8192];
  1246. X+   int nchars;
  1247. X+ 
  1248. X+   lseek (from_fd, 0, L_SET);
  1249. X+   lseek (to_fd, 0, L_SET);
  1250. X+   if (ftruncate (to_fd, 0) < 0)
  1251. X+     pfatal_with_name (to_name);
  1252. X+ 
  1253. X+   while ((nchars = read (from_fd, buf, sizeof (buf))) > 0)
  1254. X+     {
  1255. X+       if (write (to_fd, buf, nchars) != nchars) 
  1256. X+     pfatal_with_name (to_name);
  1257. X+     }
  1258. X+   if (nchars < 0)
  1259. X+     pfatal_with_name (from_name);
  1260. X+ }
  1261. X+ 
  1262. X+ /* Fill in an ar header for an element of the archive.  */
  1263. X+ 
  1264. X  void
  1265. X  header_from_map (header, mapelt)
  1266. X       struct ar_hdr *header;
  1267. X       struct mapelt *mapelt;
  1268. X  {
  1269. X    /* Zero the header, then store in the data as text.  */
  1270. X    bzero ((char *) header, sizeof (*header));
  1271. X  
  1272. X!   assert (mapelt->info.name.stored != NULL);
  1273. X!   assert (strlen (mapelt->info.name.stored) < sizeof (header->ar_name));
  1274. X!   strcpy (header->ar_name, mapelt->info.name.stored);
  1275. X  
  1276. X    sprintf (header->ar_date, "%ld", mapelt->info.date);
  1277. X    sprintf (header->ar_size, "%d", mapelt->info.size);
  1278. X***************
  1279. X*** 1047,1062 ****
  1280. X       struct mapelt *mapelt;
  1281. X       int archive_indesc;
  1282. X       int outdesc;
  1283. X  {
  1284. X    struct ar_hdr header;
  1285. X    int indesc;
  1286. X  
  1287. X!   if (mapelt->info.name == 0)
  1288. X!     /* This element was cancelled.  */
  1289. X      return;
  1290. X  
  1291. X    header_from_map (&header, mapelt);
  1292. X  
  1293. X    if (mapelt->info.offset != 0)
  1294. X      {
  1295. X        indesc = archive_indesc;
  1296. X--- 1273,1290 ----
  1297. X       struct mapelt *mapelt;
  1298. X       int archive_indesc;
  1299. X       int outdesc;
  1300. X+      char *outname;
  1301. X  {
  1302. X    struct ar_hdr header;
  1303. X    int indesc;
  1304. X  
  1305. X!   if (marked_for_deletion (mapelt))
  1306. X      return;
  1307. X  
  1308. X    header_from_map (&header, mapelt);
  1309. X  
  1310. X+   /* Either copy the member from the (old) archive, or copy it from 
  1311. X+      the user-named filed.  */
  1312. X    if (mapelt->info.offset != 0)
  1313. X      {
  1314. X        indesc = archive_indesc;
  1315. X***************
  1316. X*** 1064,1073 ****
  1317. X      }
  1318. X    else
  1319. X      {
  1320. X!       indesc = open (mapelt->info.name, 0, 0);
  1321. X        if (indesc < 0)
  1322. X      {
  1323. X!       perror_with_name (mapelt->info.name);
  1324. X        return;
  1325. X      }
  1326. X      }
  1327. X--- 1292,1302 ----
  1328. X      }
  1329. X    else
  1330. X      {
  1331. X!       assert (mapelt->info.name.given != NULL);
  1332. X!       indesc = open (mapelt->info.name.given, O_RDONLY, 0);
  1333. X        if (indesc < 0)
  1334. X      {
  1335. X!       perror_with_name (mapelt->info.name.given);
  1336. X        return;
  1337. X      }
  1338. X      }
  1339. X***************
  1340. X*** 1134,1158 ****
  1341. X  void
  1342. X  delete_members ()
  1343. X  {
  1344. X!   struct mapelt *map = make_map (0);
  1345. X!   struct mapelt *tail;
  1346. X    struct mapelt mapstart;
  1347. X!   char **p;
  1348. X  
  1349. X!   mapstart.info.name = 0;
  1350. X    mapstart.next = map;
  1351. X    map = &mapstart;
  1352. X  
  1353. X!   lock_for_update ();
  1354. X! 
  1355. X!   if (files)
  1356. X!     for (p = files; *p; p++)
  1357. X        {
  1358. X      /* If user says to delete the __.SYMDEF member,
  1359. X         don't make a new one to replace it.  */
  1360. X!     if (!strcmp (*p, "__.SYMDEF"))
  1361. X        symdef_exists = 0;
  1362. X!     delete_from_map (*p, map);
  1363. X        }
  1364. X  
  1365. X    write_archive (map->next, 0);
  1366. X--- 1363,1387 ----
  1367. X  void
  1368. X  delete_members ()
  1369. X  {
  1370. X!   struct mapelt *map;
  1371. X    struct mapelt mapstart;
  1372. X!   struct member_name *name;
  1373. X  
  1374. X!   open_archive (O_RDWR);
  1375. X! 
  1376. X!   map = make_map (0);
  1377. X!   init_elt (&mapstart);
  1378. X    mapstart.next = map;
  1379. X    map = &mapstart;
  1380. X  
  1381. X!   if (file_args)
  1382. X!     for (name = file_args; !Empty_Name(name); name++)
  1383. X        {
  1384. X      /* If user says to delete the __.SYMDEF member,
  1385. X         don't make a new one to replace it.  */
  1386. X!     if (name_match (name, &symdef_name))
  1387. X        symdef_exists = 0;
  1388. X!     delete_from_map (name, map);
  1389. X        }
  1390. X  
  1391. X    write_archive (map->next, 0);
  1392. X***************
  1393. X*** 1160,1191 ****
  1394. X  
  1395. X  void
  1396. X  delete_from_map (name, map)
  1397. X!      char *name;
  1398. X       struct mapelt *map;
  1399. X  {
  1400. X    struct mapelt *this = find_mapelt (map, name);
  1401. X  
  1402. X    if (!this) return;
  1403. X!   this->info.name = 0;
  1404. X    if (verbose)
  1405. X!     printf ("d - %s\n", name);
  1406. X  }
  1407. X  
  1408. X  void
  1409. X  move_members ()
  1410. X  {
  1411. X!   struct mapelt *map = make_map (0);
  1412. X!   char **p;
  1413. X    struct mapelt *after_mapelt;
  1414. X    struct mapelt mapstart;
  1415. X    struct mapelt *change_map;
  1416. X  
  1417. X!   mapstart.info.name = 0;
  1418. X    mapstart.next = map;
  1419. X    change_map = &mapstart;
  1420. X  
  1421. X-   lock_for_update ();
  1422. X- 
  1423. X    switch (postype)
  1424. X      {
  1425. X      case POS_DEFAULT:
  1426. X--- 1389,1421 ----
  1427. X  
  1428. X  void
  1429. X  delete_from_map (name, map)
  1430. X!      struct member_name *name;
  1431. X       struct mapelt *map;
  1432. X  {
  1433. X    struct mapelt *this = find_mapelt (map, name);
  1434. X  
  1435. X    if (!this) return;
  1436. X!   mark_as_deleted (this);
  1437. X    if (verbose)
  1438. X!     printf ("d - %s\n", name->stored);
  1439. X  }
  1440. X  
  1441. X  void
  1442. X  move_members ()
  1443. X  {
  1444. X!   struct mapelt *map;
  1445. X!   struct member_name *name;
  1446. X    struct mapelt *after_mapelt;
  1447. X    struct mapelt mapstart;
  1448. X    struct mapelt *change_map;
  1449. X  
  1450. X!   open_archive (O_RDWR);
  1451. X! 
  1452. X!   map = make_map (0);
  1453. X!   init_elt (&mapstart);
  1454. X    mapstart.next = map;
  1455. X    change_map = &mapstart;
  1456. X  
  1457. X    switch (postype)
  1458. X      {
  1459. X      case POS_DEFAULT:
  1460. X***************
  1461. X*** 1197,1203 ****
  1462. X        break;
  1463. X  
  1464. X      case POS_BEFORE:
  1465. X!       after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname));
  1466. X      }
  1467. X  
  1468. X    /* Failure to find specified "before" or "after" member
  1469. X--- 1427,1439 ----
  1470. X        break;
  1471. X  
  1472. X      case POS_BEFORE:
  1473. X!       after_mapelt = prev_mapelt (change_map, find_mapelt (map,
  1474. X!                                posname));
  1475. X!       break;
  1476. X! 
  1477. X!     default:
  1478. X!       after_mapelt = 0;            /* lint */
  1479. X!       fatal ("bogus position type");    /* "can't happen" */
  1480. X      }
  1481. X  
  1482. X    /* Failure to find specified "before" or "after" member
  1483. X***************
  1484. X*** 1205,1230 ****
  1485. X  
  1486. X    if (!after_mapelt) exit (1);
  1487. X  
  1488. X!   if (files)
  1489. X!     for (p = files; *p; p++)
  1490. X        {
  1491. X!     if (move_in_map (*p, change_map, after_mapelt))
  1492. X        after_mapelt = after_mapelt->next;
  1493. X        }
  1494. X  
  1495. X!   write_archive (map, 0);
  1496. X  }
  1497. X  
  1498. X  int
  1499. X  move_in_map (name, map, after)
  1500. X!      char *name;
  1501. X       struct mapelt *map, *after;
  1502. X  {
  1503. X    struct mapelt *this = find_mapelt (map, name);
  1504. X    struct mapelt *prev;
  1505. X  
  1506. X!   if (!this) return 0;
  1507. X    prev = prev_mapelt (map, this);
  1508. X    prev->next = this->next;
  1509. X    this->next = after->next;
  1510. X    after->next = this;
  1511. X--- 1441,1469 ----
  1512. X  
  1513. X    if (!after_mapelt) exit (1);
  1514. X  
  1515. X!   if (file_args)
  1516. X!     for (name = file_args; !Empty_Name(name); name++)
  1517. X        {
  1518. X!     if (move_in_map (name, change_map, after_mapelt))
  1519. X        after_mapelt = after_mapelt->next;
  1520. X        }
  1521. X  
  1522. X!   write_archive (change_map->next, 0);
  1523. X  }
  1524. X  
  1525. X  int
  1526. X  move_in_map (name, map, after)
  1527. X!      struct member_name *name;
  1528. X       struct mapelt *map, *after;
  1529. X  {
  1530. X    struct mapelt *this = find_mapelt (map, name);
  1531. X    struct mapelt *prev;
  1532. X  
  1533. X!   if (!this)
  1534. X!     return 0;
  1535. X    prev = prev_mapelt (map, this);
  1536. X+   if (this == after || prev == after)
  1537. X+     return 1;                /* no-op */
  1538. X    prev->next = this->next;
  1539. X    this->next = after->next;
  1540. X    after->next = this;
  1541. X***************
  1542. X*** 1236,1254 ****
  1543. X  void
  1544. X  replace_members ()
  1545. X  {
  1546. X!   struct mapelt *map = make_map (1);
  1547. X    struct mapelt mapstart;
  1548. X    struct mapelt *after_mapelt;
  1549. X    struct mapelt *change_map;
  1550. X!   char **p;
  1551. X    int changed;
  1552. X  
  1553. X!   mapstart.info.name = 0;
  1554. X    mapstart.next = map;
  1555. X    change_map = &mapstart;
  1556. X  
  1557. X-   lock_for_update ();
  1558. X- 
  1559. X    switch (postype)
  1560. X      {
  1561. X      case POS_DEFAULT:
  1562. X--- 1475,1494 ----
  1563. X  void
  1564. X  replace_members ()
  1565. X  {
  1566. X!   struct mapelt *map;
  1567. X    struct mapelt mapstart;
  1568. X    struct mapelt *after_mapelt;
  1569. X    struct mapelt *change_map;
  1570. X!   struct member_name *name;
  1571. X    int changed;
  1572. X  
  1573. X!   open_archive (O_RDWR);
  1574. X! 
  1575. X!   map = make_map (1);
  1576. X!   init_elt (&mapstart);
  1577. X    mapstart.next = map;
  1578. X    change_map = &mapstart;
  1579. X  
  1580. X    switch (postype)
  1581. X      {
  1582. X      case POS_DEFAULT:
  1583. X***************
  1584. X*** 1261,1266 ****
  1585. X--- 1501,1511 ----
  1586. X  
  1587. X      case POS_BEFORE:
  1588. X        after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname));
  1589. X+       break;
  1590. X+ 
  1591. X+     default:
  1592. X+       after_mapelt = 0;            /* lint */
  1593. X+       fatal ("bogus position type");    /* "can't happen" */
  1594. X      }
  1595. X  
  1596. X    /* Failure to find specified "before" or "after" member
  1597. X***************
  1598. X*** 1269,1288 ****
  1599. X      exit (1);
  1600. X  
  1601. X    changed = 0;
  1602. X!   if (files != 0)
  1603. X!     for (p = files; *p != 0; ++p)
  1604. X!       if (insert_in_map (*p, change_map, after_mapelt))
  1605. X      {
  1606. X        after_mapelt = after_mapelt->next;
  1607. X        changed = 1;
  1608. X      }
  1609. X  
  1610. X-   change_map = change_map->next;
  1611. X    if (!changed && (!symdef_flag || symdef_exists))
  1612. X      /* Nothing changed.  */
  1613. X!     close_archive (change_map);
  1614. X    else
  1615. X!     write_archive (change_map, 0);
  1616. X  }
  1617. X  
  1618. X  /* Handle the "quick insert" operation.  */
  1619. X--- 1514,1532 ----
  1620. X      exit (1);
  1621. X  
  1622. X    changed = 0;
  1623. X!   if (file_args)
  1624. X!     for (name = file_args; !Empty_Name(name); ++name)
  1625. X!       if (insert_in_map (name, change_map, after_mapelt))
  1626. X      {
  1627. X        after_mapelt = after_mapelt->next;
  1628. X        changed = 1;
  1629. X      }
  1630. X  
  1631. X    if (!changed && (!symdef_flag || symdef_exists))
  1632. X      /* Nothing changed.  */
  1633. X!     close_archive ();
  1634. X    else
  1635. X!     write_archive (change_map->next, 0);
  1636. X  }
  1637. X  
  1638. X  /* Handle the "quick insert" operation.  */
  1639. X***************
  1640. X*** 1293,1314 ****
  1641. X    struct mapelt *map;
  1642. X    struct mapelt *after;
  1643. X    struct mapelt mapstart;
  1644. X!   char **p;
  1645. X  
  1646. X!   mapstart.info.name = 0;
  1647. X    mapstart.next = 0;
  1648. X    map = &mapstart;
  1649. X    after = map;
  1650. X  
  1651. X!   lock_for_update ();
  1652. X  
  1653. X    /* Insert the specified files into the "map",
  1654. X       but is a map of the inserted files only,
  1655. X       and starts out empty.  */
  1656. X!   if (files)
  1657. X!     for (p = files; *p; p++)
  1658. X        {
  1659. X!     if (insert_in_map (*p, map, after))
  1660. X        after = after->next;
  1661. X        }
  1662. X  
  1663. X--- 1537,1558 ----
  1664. X    struct mapelt *map;
  1665. X    struct mapelt *after;
  1666. X    struct mapelt mapstart;
  1667. X!   struct member_name *name;
  1668. X  
  1669. X!   init_elt (&mapstart);
  1670. X    mapstart.next = 0;
  1671. X    map = &mapstart;
  1672. X    after = map;
  1673. X  
  1674. X!   open_archive (O_RDWR);
  1675. X  
  1676. X    /* Insert the specified files into the "map",
  1677. X       but is a map of the inserted files only,
  1678. X       and starts out empty.  */
  1679. X!   if (file_args)
  1680. X!     for (name = file_args; !Empty_Name(name); name++)
  1681. X        {
  1682. X!     if (insert_in_map (name, map, after))
  1683. X        after = after->next;
  1684. X        }
  1685. X  
  1686. X***************
  1687. X*** 1317,1350 ****
  1688. X    write_archive (map->next, 1);
  1689. X  }
  1690. X  
  1691. X! /* Insert an entry for name NAME into the map MAP after the map entry AFTER.
  1692. X!    Delete an old entry for NAME.
  1693. X     MAP is assumed to start with a dummy entry, which facilitates
  1694. X     insertion at the beginning of the list.
  1695. X!    Return 1 if successful, 0 if did nothing because file NAME doesn't
  1696. X!    exist or (optionally) is older.  */
  1697. X  
  1698. X  int
  1699. X! insert_in_map (name, map, after)
  1700. X!      char *name;
  1701. X       struct mapelt *map, *after;
  1702. X  {
  1703. X!   struct mapelt *old = find_mapelt_noerror (map, name);
  1704. X    struct mapelt *this;
  1705. X    struct stat status;
  1706. X  
  1707. X!   if (stat (name, &status))
  1708. X      {
  1709. X!       perror_with_name (name);
  1710. X        return 0;
  1711. X      }
  1712. X    if (old && newer_only && status.st_mtime <= old->info.date)
  1713. X      return 0;
  1714. X!   if (old)
  1715. X!     /* Delete the old one.  */
  1716. X!     old->info.name = 0;
  1717. X    this = (struct mapelt *) xmalloc (sizeof (struct mapelt));
  1718. X!   this->info.name = name;
  1719. X    this->info.offset = 0;
  1720. X    this->info.data_offset = 0;
  1721. X    this->info.date = status.st_mtime;
  1722. X--- 1561,1597 ----
  1723. X    write_archive (map->next, 1);
  1724. X  }
  1725. X  
  1726. X! /* Insert an entry for REQUESTED_NAME into the map MAP after the map
  1727. X!    entry AFTER. 
  1728. X!    Deletes any old entry for REQUESTED_NAME.
  1729. X     MAP is assumed to start with a dummy entry, which facilitates
  1730. X     insertion at the beginning of the list.
  1731. X!    Return 1 if successful, 0 if did nothing because file
  1732. X!    REQUESTED_NAME doesn't exist or (optionally) is older.  */
  1733. X  
  1734. X  int
  1735. X! insert_in_map (requested_name, map, after)
  1736. X!      struct member_name *requested_name;
  1737. X       struct mapelt *map, *after;
  1738. X  {
  1739. X!   struct mapelt *old = find_mapelt_noerror (map, requested_name);
  1740. X    struct mapelt *this;
  1741. X    struct stat status;
  1742. X  
  1743. X!   assert (requested_name->given != NULL);
  1744. X!   if (stat (requested_name->given, &status))
  1745. X      {
  1746. X!       perror_with_name (requested_name->given);
  1747. X        return 0;
  1748. X      }
  1749. X    if (old && newer_only && status.st_mtime <= old->info.date)
  1750. X      return 0;
  1751. X! 
  1752. X    this = (struct mapelt *) xmalloc (sizeof (struct mapelt));
  1753. X!   if (old)
  1754. X!     mark_as_deleted (old);
  1755. X! 
  1756. X!   this->info.name = *requested_name;
  1757. X    this->info.offset = 0;
  1758. X    this->info.data_offset = 0;
  1759. X    this->info.date = status.st_mtime;
  1760. X***************
  1761. X*** 1356,1362 ****
  1762. X    after->next = this;
  1763. X  
  1764. X    if (verbose)
  1765. X!     printf ("%c - %s\n", old == 0 ? 'a' : 'r', this->info.name);
  1766. X  
  1767. X    return 1;
  1768. X  }
  1769. X--- 1603,1609 ----
  1770. X    after->next = this;
  1771. X  
  1772. X    if (verbose)
  1773. X!     printf ("%c - %s\n", old == 0 ? 'a' : 'r', this->info.name.stored);
  1774. X  
  1775. X    return 1;
  1776. X  }
  1777. X***************
  1778. X*** 1369,1378 ****
  1779. X       void (*function) ();
  1780. X  {
  1781. X    struct mapelt *map;
  1782. X!   FILE *arcstream;
  1783. X!   char **p;
  1784. X  
  1785. X!   if (!files)
  1786. X      {
  1787. X        /* Handle case where we want to operate on every member.
  1788. X       No need to make a map and search it for this.  */
  1789. X--- 1616,1624 ----
  1790. X       void (*function) ();
  1791. X  {
  1792. X    struct mapelt *map;
  1793. X!   struct member_name *name;
  1794. X  
  1795. X!   if (!file_args)
  1796. X      {
  1797. X        /* Handle case where we want to operate on every member.
  1798. X       No need to make a map and search it for this.  */
  1799. X***************
  1800. X*** 1380,1398 ****
  1801. X        return;
  1802. X      }
  1803. X  
  1804. X!   arcstream = fopen (archive, "r");
  1805. X!   if (!arcstream)
  1806. X      fatal ("failure opening archive %s for the second time", archive);
  1807. X    map = make_map (0);
  1808. X  
  1809. X!   for (p = files; *p; p++)
  1810. X      {
  1811. X!       struct mapelt *this = find_mapelt (map, *p);
  1812. X        if (!this) continue;
  1813. X        function (this->info, arcstream);
  1814. X      }
  1815. X- 
  1816. X-   fclose (arcstream);
  1817. X  }
  1818. X  
  1819. X  /* Write the __.SYMDEF member from data in core.  OUTDESC and OUTNAME
  1820. X--- 1626,1644 ----
  1821. X        return;
  1822. X      }
  1823. X  
  1824. X!   if (arcstream == 0)
  1825. X!     open_archive (O_RDONLY);
  1826. X!   if (arcstream == 0)
  1827. X      fatal ("failure opening archive %s for the second time", archive);
  1828. X+   verify_is_archive (arcfd);
  1829. X    map = make_map (0);
  1830. X  
  1831. X!   for (name = file_args; !Empty_Name(name); name++)
  1832. X      {
  1833. X!       struct mapelt *this = find_mapelt (map, name);
  1834. X        if (!this) continue;
  1835. X        function (this->info, arcstream);
  1836. X      }
  1837. X  }
  1838. X  
  1839. X  /* Write the __.SYMDEF member from data in core.  OUTDESC and OUTNAME
  1840. X***************
  1841. X*** 1406,1417 ****
  1842. X       char *outname;
  1843. X  {
  1844. X    struct ar_hdr header;
  1845. X-   int indesc;
  1846. X    struct mapelt *mapptr;
  1847. X    unsigned long int symdefs_size;
  1848. X  
  1849. X!   if (mapelt->info.name == 0)
  1850. X!     /* This element was cancelled.  */
  1851. X      return;
  1852. X  
  1853. X    header_from_map (&header, mapelt);
  1854. X--- 1652,1662 ----
  1855. X       char *outname;
  1856. X  {
  1857. X    struct ar_hdr header;
  1858. X    struct mapelt *mapptr;
  1859. X    unsigned long int symdefs_size;
  1860. X+   int symdef_sanity_count;
  1861. X  
  1862. X!   if (marked_for_deletion (mapelt))
  1863. X      return;
  1864. X  
  1865. X    header_from_map (&header, mapelt);
  1866. X***************
  1867. X*** 1420,1426 ****
  1868. X  
  1869. X    mywrite (outdesc, &header, sizeof (header), outname);
  1870. X  
  1871. X!   /* Write the number of symdefs.  */
  1872. X    symdefs_size = nsymdefs * sizeof (struct symdef);
  1873. X    mywrite (outdesc, &symdefs_size, sizeof symdefs_size, outname);
  1874. X  
  1875. X--- 1665,1671 ----
  1876. X  
  1877. X    mywrite (outdesc, &header, sizeof (header), outname);
  1878. X  
  1879. X!   /* Write the number of bytes taken by the symdef table.  */
  1880. X    symdefs_size = nsymdefs * sizeof (struct symdef);
  1881. X    mywrite (outdesc, &symdefs_size, sizeof symdefs_size, outname);
  1882. X  
  1883. X***************
  1884. X*** 1427,1439 ****
  1885. X    /* Write symdefs surviving from old archive.  */
  1886. X    mywrite (outdesc, old_symdefs, num_old_symdefs * sizeof (struct symdef),
  1887. X         outname);
  1888. X  
  1889. X    /* Write symdefs for new members.  */
  1890. X    for (mapptr = map; mapptr != 0; mapptr = mapptr->next)
  1891. X      if (mapptr->info.nsymdefs != 0)
  1892. X!       write (outdesc, mapptr->info.symdefs,
  1893. X!          mapptr->info.nsymdefs * sizeof (struct symdef));
  1894. X  
  1895. X    /* Write the string table size.  */
  1896. X    mywrite (outdesc, &new_strings_size, sizeof new_strings_size, outname);
  1897. X  
  1898. X--- 1672,1699 ----
  1899. X    /* Write symdefs surviving from old archive.  */
  1900. X    mywrite (outdesc, old_symdefs, num_old_symdefs * sizeof (struct symdef),
  1901. X         outname);
  1902. X+   symdef_sanity_count = num_old_symdefs;
  1903. X+ 
  1904. X+ #if DEBUG
  1905. X+   verify_symdefs (map, old_symdefs, num_old_symdefs, new_strings);
  1906. X+ #endif
  1907. X  
  1908. X    /* Write symdefs for new members.  */
  1909. X    for (mapptr = map; mapptr != 0; mapptr = mapptr->next)
  1910. X      if (mapptr->info.nsymdefs != 0)
  1911. X!       {
  1912. X!     write (outdesc, mapptr->info.symdefs,
  1913. X!            mapptr->info.nsymdefs * sizeof (struct symdef));
  1914. X! #if DEBUG
  1915. X!     verify_symdefs (map, mapptr->info.symdefs, mapptr->info.nsymdefs,
  1916. X!             new_strings);
  1917. X! #endif
  1918. X!     symdef_sanity_count += mapptr->info.nsymdefs;
  1919. X!       }
  1920. X  
  1921. X+   if (symdef_sanity_count != nsymdefs)
  1922. X+     fatal ("bug: wrote wrong number of symdefs");
  1923. X+ 
  1924. X    /* Write the string table size.  */
  1925. X    mywrite (outdesc, &new_strings_size, sizeof new_strings_size, outname);
  1926. X  
  1927. X***************
  1928. X*** 1444,1449 ****
  1929. X--- 1704,1764 ----
  1930. X      mywrite (outdesc, "", 1, outname);
  1931. X  }
  1932. X  
  1933. X+ #if DEBUG
  1934. X+ 
  1935. X+ /* Verify that the given symdefs point to the right place.  Treat the
  1936. X+    symbol as the name of a .o file and look it up.  If we find it,
  1937. X+    make sure we are pointing to it and not to some other .o file.  */
  1938. X+ 
  1939. X+ void
  1940. X+ verify_symdefs (map, symdefs, numsymdefs, string_table)
  1941. X+      struct mapelt *map;
  1942. X+      struct symdef *symdefs;
  1943. X+      unsigned int numsymdefs;
  1944. X+      char *string_table;
  1945. X+ {
  1946. X+   struct symdef *sym;
  1947. X+   struct member_name file_name;
  1948. X+   struct mapelt *member;
  1949. X+   char *tmp_name;
  1950. X+ 
  1951. X+   for (sym = symdefs; sym < symdefs+numsymdefs; ++sym)
  1952. X+     {
  1953. X+       tmp_name = concat (string_table + sym->s.stringoffset, ".o", "");
  1954. X+       init_name (&file_name, (tmp_name[0] == '_' ? tmp_name+1 : tmp_name));
  1955. X+       member = find_mapelt_noerror (map, &file_name);
  1956. X+       if (member)
  1957. X+     {
  1958. X+       if (member->info.new_offset)
  1959. X+         {
  1960. X+           if (member->info.new_offset != sym->offset)
  1961. X+         {
  1962. X+           printf ("Symbol %s points to 0x%x, which doesn't match \
  1963. X+ 0x%x (old 0x%x)\n",
  1964. X+               string_table + sym->s.stringoffset,
  1965. X+               sym->offset,
  1966. X+               member->info.new_offset,
  1967. X+               member->info.offset);
  1968. X+           abort ();
  1969. X+         }
  1970. X+         }
  1971. X+       /* else no new offset, so check the old one */
  1972. X+       else if (member->info.offset != sym->offset)
  1973. X+         {
  1974. X+           printf ("Symbol %s points to 0x%x, which doesn't match 0x%x\n",
  1975. X+               string_table + sym->s.stringoffset,
  1976. X+               sym->offset,
  1977. X+               member->info.offset);
  1978. X+           abort();
  1979. X+         }
  1980. X+     }
  1981. X+       free_name_strings (&file_name);
  1982. X+       free (tmp_name);
  1983. X+     }
  1984. X+ }
  1985. X+ 
  1986. X+ #endif /* DEBUG */
  1987. X+ 
  1988. X  void
  1989. X  read_old_symdefs (map, archive_indesc)
  1990. X       struct mapelt *map;
  1991. X***************
  1992. X*** 1451,1474 ****
  1993. X  {
  1994. X    struct mapelt *mapelt;
  1995. X    char *data;
  1996. X-   int val;
  1997. X    int symdefs_size;
  1998. X  
  1999. X!   mapelt = find_mapelt_noerror (map, "__.SYMDEF");
  2000. X    if (!mapelt)
  2001. X      abort ();            /* Only call here if an old one exists */
  2002. X  
  2003. X    data  = (char *) xmalloc (mapelt->info.size);
  2004. X    lseek (archive_indesc, mapelt->info.data_offset, 0);
  2005. X!   val = read (archive_indesc, data, mapelt->info.size);
  2006. X  
  2007. X    symdefs_size = *(unsigned long int *) data;
  2008. X    original_num_symdefs = symdefs_size / sizeof (struct symdef);
  2009. X    old_symdefs = (struct symdef *) (data + sizeof (symdefs_size));
  2010. X-   old_strings = ((char *) (old_symdefs + original_num_symdefs)
  2011. X-          + sizeof (symdefs_size));
  2012. X    old_strings_size
  2013. X      = *(unsigned long int *) (old_symdefs + original_num_symdefs);
  2014. X  }
  2015. X  
  2016. X  /* Read various information from the header of an object file.
  2017. X--- 1766,1793 ----
  2018. X  {
  2019. X    struct mapelt *mapelt;
  2020. X    char *data;
  2021. X    int symdefs_size;
  2022. X  
  2023. X!   mapelt = find_mapelt_noerror (map, &symdef_name);
  2024. X    if (!mapelt)
  2025. X      abort ();            /* Only call here if an old one exists */
  2026. X  
  2027. X    data  = (char *) xmalloc (mapelt->info.size);
  2028. X    lseek (archive_indesc, mapelt->info.data_offset, 0);
  2029. X!   if (read (archive_indesc, data, mapelt->info.size) !=
  2030. X!       mapelt->info.size)
  2031. X!     pfatal_with_name (archive);
  2032. X  
  2033. X    symdefs_size = *(unsigned long int *) data;
  2034. X    original_num_symdefs = symdefs_size / sizeof (struct symdef);
  2035. X    old_symdefs = (struct symdef *) (data + sizeof (symdefs_size));
  2036. X    old_strings_size
  2037. X      = *(unsigned long int *) (old_symdefs + original_num_symdefs);
  2038. X+   old_strings = ((char *) (old_symdefs + original_num_symdefs)
  2039. X+          + sizeof (old_strings_size));
  2040. X+ #if DEBUG
  2041. X+   verify_symdefs (map, old_symdefs, original_num_symdefs, old_strings);
  2042. X+ #endif
  2043. X  }
  2044. X  
  2045. X  /* Read various information from the header of an object file.
  2046. X***************
  2047. X*** 1475,1481 ****
  2048. X     Return 0 for failure or 1 for success.  */
  2049. X  
  2050. X  int
  2051. X! read_header_info (mapelt, desc, offset, syms_offset, syms_size, strs_offset, strs_size)
  2052. X       struct mapelt *mapelt;
  2053. X       int desc;
  2054. X       long int offset;
  2055. X--- 1794,1801 ----
  2056. X     Return 0 for failure or 1 for success.  */
  2057. X  
  2058. X  int
  2059. X! read_header_info (mapelt, desc, offset, syms_offset, syms_size, strs_offset,
  2060. X!           strs_size)
  2061. X       struct mapelt *mapelt;
  2062. X       int desc;
  2063. X       long int offset;
  2064. X***************
  2065. X*** 1563,1569 ****
  2066. X       int archive_indesc;
  2067. X  {
  2068. X    int indesc;
  2069. X-   char *name = mapelt->info.name;
  2070. X    long int syms_offset, strs_offset;
  2071. X    unsigned int syms_size, strs_size;
  2072. X    struct nlist *symbols;
  2073. X--- 1883,1888 ----
  2074. X***************
  2075. X*** 1572,1581 ****
  2076. X    register unsigned int i;
  2077. X    unsigned long int offset;
  2078. X  
  2079. X!   if (name == 0)
  2080. X!     /* Deleted member.  */
  2081. X!     abort ();
  2082. X  
  2083. X    if (mapelt->info.offset != 0)
  2084. X      {
  2085. X        indesc = archive_indesc;
  2086. X--- 1891,1902 ----
  2087. X    register unsigned int i;
  2088. X    unsigned long int offset;
  2089. X  
  2090. X!   if (marked_for_deletion (mapelt))
  2091. X!     fatal ("trying to make symdefs for deleted member");
  2092. X  
  2093. X+   /* Either use an existing member from the archive, or use the 
  2094. X+      user-specified file.  */
  2095. X+ 
  2096. X    if (mapelt->info.offset != 0)
  2097. X      {
  2098. X        indesc = archive_indesc;
  2099. X***************
  2100. X*** 1584,1599 ****
  2101. X      }
  2102. X    else
  2103. X      {
  2104. X!       indesc = open (mapelt->info.name, 0, 0);
  2105. X        if (indesc < 0)
  2106. X      {
  2107. X!       perror_with_name (mapelt->info.name);
  2108. X        return;
  2109. X      }
  2110. X        offset = 0;
  2111. X      }
  2112. X  
  2113. X!   if (!read_header_info (mapelt, indesc, offset, &syms_offset, &syms_size, &strs_offset, &strs_size))
  2114. X      {
  2115. X        if (mapelt->info.offset == 0)
  2116. X      close (indesc);
  2117. X--- 1905,1922 ----
  2118. X      }
  2119. X    else
  2120. X      {
  2121. X!       assert (mapelt->info.name.given != NULL);
  2122. X!       indesc = open (mapelt->info.name.given, O_RDONLY, 0);
  2123. X        if (indesc < 0)
  2124. X      {
  2125. X!       perror_with_name (mapelt->info.name.given);
  2126. X        return;
  2127. X      }
  2128. X        offset = 0;
  2129. X      }
  2130. X  
  2131. X!   if (!read_header_info (mapelt, indesc, (long) offset, &syms_offset,
  2132. X!              &syms_size, &strs_offset, &strs_size))
  2133. X      {
  2134. X        if (mapelt->info.offset == 0)
  2135. X      close (indesc);
  2136. X***************
  2137. X*** 1641,1647 ****
  2138. X      (void) close (indesc);
  2139. X  
  2140. X    /* Discard the symbols we don't want to mention; compact the rest down.  */
  2141. X!   symcount = filter_symbols (symbols, symcount);
  2142. X  
  2143. X    mapelt->info.symdefs = (struct symdef *)
  2144. X      xmalloc (symcount * sizeof (struct symdef));
  2145. X--- 1964,1970 ----
  2146. X      (void) close (indesc);
  2147. X  
  2148. X    /* Discard the symbols we don't want to mention; compact the rest down.  */
  2149. X!   symcount = filter_symbols (symbols, (unsigned) symcount);
  2150. X  
  2151. X    mapelt->info.symdefs = (struct symdef *)
  2152. X      xmalloc (symcount * sizeof (struct symdef));
  2153. X***************
  2154. X*** 1699,1704 ****
  2155. X--- 2022,2028 ----
  2156. X    unsigned int len;
  2157. X    struct symdef *s;
  2158. X    unsigned long int deleted_strings_size = 0;
  2159. X+   unsigned long *newoffsets = 0;
  2160. X  
  2161. X    nsymdefs = original_num_symdefs;
  2162. X    num_old_symdefs = original_num_symdefs;
  2163. X***************
  2164. X*** 1708,1721 ****
  2165. X      {
  2166. X        /* We already had a __.SYMDEF member, so just update it.  */
  2167. X  
  2168. X!       /* Mark as canceled any old symdefs for members being deleted.  */
  2169. X  
  2170. X        for (tail = map; tail != 0; tail = tail->next)
  2171. X      {
  2172. X!       if (tail->info.name == 0)
  2173. X          {
  2174. X            /* Old member being deleted.  Delete its symdef entries too.  */
  2175. X!           for (i = 0; i < nsymdefs; i++)
  2176. X          if (old_symdefs[i].offset == tail->info.offset)
  2177. X            {
  2178. X              old_symdefs[i].offset = 0;
  2179. X--- 2032,2046 ----
  2180. X      {
  2181. X        /* We already had a __.SYMDEF member, so just update it.  */
  2182. X  
  2183. X!       /* Mark as cancelled any old symdefs for members being deleted.  */
  2184. X  
  2185. X        for (tail = map; tail != 0; tail = tail->next)
  2186. X      {
  2187. X!       if (marked_for_deletion (tail))
  2188. X          {
  2189. X+           assert (tail->info.offset != 0);
  2190. X            /* Old member being deleted.  Delete its symdef entries too.  */
  2191. X!           for (i = 0; i < original_num_symdefs; i++)
  2192. X          if (old_symdefs[i].offset == tail->info.offset)
  2193. X            {
  2194. X              old_symdefs[i].offset = 0;
  2195. X***************
  2196. X*** 1744,1751 ****
  2197. X        for (tail = map; tail != 0; tail = tail->next)
  2198. X      {
  2199. X        if (tail->info.offset != 0
  2200. X!           || tail->info.name == 0
  2201. X!           || !strcmp (tail->info.name, "__.SYMDEF"))
  2202. X          continue;
  2203. X        make_new_symdefs (tail, archive_indesc);
  2204. X        nsymdefs += tail->info.nsymdefs;
  2205. X--- 2069,2076 ----
  2206. X        for (tail = map; tail != 0; tail = tail->next)
  2207. X      {
  2208. X        if (tail->info.offset != 0
  2209. X!           || marked_for_deletion (tail)
  2210. X!           || name_match (&tail->info.name, &symdef_name))
  2211. X          continue;
  2212. X        make_new_symdefs (tail, archive_indesc);
  2213. X        nsymdefs += tail->info.nsymdefs;
  2214. X***************
  2215. X*** 1758,1765 ****
  2216. X  
  2217. X        for (tail = map; tail != 0; tail = tail->next)
  2218. X      {
  2219. X!       if (tail->info.name == 0
  2220. X!           || !strcmp (tail->info.name, "__.SYMDEF"))
  2221. X          continue;
  2222. X        make_new_symdefs (tail, archive_indesc);
  2223. X        nsymdefs += tail->info.nsymdefs;
  2224. X--- 2083,2090 ----
  2225. X  
  2226. X        for (tail = map; tail != 0; tail = tail->next)
  2227. X      {
  2228. X!       if (marked_for_deletion (tail)
  2229. X!           || name_match (&tail->info.name, &symdef_name))
  2230. X          continue;
  2231. X        make_new_symdefs (tail, archive_indesc);
  2232. X        nsymdefs += tail->info.nsymdefs;
  2233. X***************
  2234. X*** 1770,1779 ****
  2235. X    new_strings_size -= deleted_strings_size;
  2236. X    old_strings_size -= deleted_strings_size;
  2237. X  
  2238. X    /* Now we know the size of __.SYMDEF,
  2239. X       so assign the positions of all the members.  */
  2240. X  
  2241. X!   tail = find_mapelt_noerror (map, "__.SYMDEF");
  2242. X    tail->info.size = (sizeof (nsymdefs) + (nsymdefs * sizeof (struct symdef))
  2243. X               + sizeof (new_strings_size) + new_strings_size);
  2244. X    symdef_mapelt = tail;
  2245. X--- 2095,2108 ----
  2246. X    new_strings_size -= deleted_strings_size;
  2247. X    old_strings_size -= deleted_strings_size;
  2248. X  
  2249. X+ #if DEBUG
  2250. X+   verify_symdefs (map, old_symdefs, num_old_symdefs, old_strings);
  2251. X+ #endif
  2252. X+ 
  2253. X    /* Now we know the size of __.SYMDEF,
  2254. X       so assign the positions of all the members.  */
  2255. X  
  2256. X!   tail = find_mapelt_noerror (map, &symdef_name);
  2257. X    tail->info.size = (sizeof (nsymdefs) + (nsymdefs * sizeof (struct symdef))
  2258. X               + sizeof (new_strings_size) + new_strings_size);
  2259. X    symdef_mapelt = tail;
  2260. X***************
  2261. X*** 1781,1788 ****
  2262. X    pos = SARMAG;
  2263. X    for (tail = map; tail != 0; tail = tail->next)
  2264. X      {
  2265. X!       if (tail->info.name == 0)
  2266. X!     /* Ignore deleted members.  */
  2267. X      continue;
  2268. X        tail->info.new_offset = pos;
  2269. X        pos += sizeof (struct ar_hdr) + tail->info.size;
  2270. X--- 2110,2116 ----
  2271. X    pos = SARMAG;
  2272. X    for (tail = map; tail != 0; tail = tail->next)
  2273. X      {
  2274. X!       if (marked_for_deletion (tail))
  2275. X      continue;
  2276. X        tail->info.new_offset = pos;
  2277. X        pos += sizeof (struct ar_hdr) + tail->info.size;
  2278. X***************
  2279. X*** 1790,1815 ****
  2280. X      ++pos;
  2281. X      }
  2282. X  
  2283. X!   /* Now update the offsets in the symdef data
  2284. X!      to be the new offsets rather than the old ones.  */
  2285. X  
  2286. X    for (tail = map; tail != 0; tail = tail->next)
  2287. X      {
  2288. X!       if (tail->info.name == 0)
  2289. X      continue;
  2290. X        if (tail->info.symdefs == 0)
  2291. X!     /* Member without new symdef data.
  2292. X!        Check the old symdef data; it may be included there. */
  2293. X!     for (i = 0; i < num_old_symdefs; i++)
  2294. X!       {
  2295. X!         if (old_symdefs[i].offset == tail->info.offset)
  2296. X!           old_symdefs[i].offset = tail->info.new_offset;
  2297. X!       }
  2298. X        else
  2299. X      for (i = 0; i < tail->info.nsymdefs; i++)
  2300. X        tail->info.symdefs[i].offset = tail->info.new_offset;
  2301. X      }
  2302. X  
  2303. X    /* Generate new, combined string table and put each string's offset into the
  2304. X       symdef that refers to it.  Note that old symdefs ref their strings by
  2305. X       offsets into old_strings but new symdefs contain addresses of strings.  */
  2306. X--- 2118,2166 ----
  2307. X      ++pos;
  2308. X      }
  2309. X  
  2310. X!   /* Now update the offsets in the symdef data to be the new offsets
  2311. X!      rather than the old ones.  We can't update the old symdefs in
  2312. X!      place, because the new offset for one member might match the old
  2313. X!      offset for another member.  So for the old symdefs we mark in a
  2314. X!      separate array what the new offsets are and then update the
  2315. X!      symdefs after going through all the members.  */
  2316. X! 
  2317. X!   newoffsets =
  2318. X!     (unsigned long *)xmalloc (num_old_symdefs * sizeof(unsigned long));
  2319. X!   bzero (newoffsets, num_old_symdefs * sizeof (unsigned long));
  2320. X  
  2321. X    for (tail = map; tail != 0; tail = tail->next)
  2322. X      {
  2323. X!       if (marked_for_deletion (tail))
  2324. X      continue;
  2325. X        if (tail->info.symdefs == 0)
  2326. X!     {
  2327. X!       /* Member without new symdef data.
  2328. X!          Check the old symdef data; it may be included there. */
  2329. X!       assert (tail->info.offset != 0);
  2330. X!       for (i = 0; i < num_old_symdefs; i++)
  2331. X!         {
  2332. X!           if (old_symdefs[i].offset == tail->info.offset)
  2333. X!         newoffsets[i] = tail->info.new_offset;
  2334. X!         }
  2335. X!     }
  2336. X        else
  2337. X      for (i = 0; i < tail->info.nsymdefs; i++)
  2338. X        tail->info.symdefs[i].offset = tail->info.new_offset;
  2339. X      }
  2340. X  
  2341. X+   /* Actually update any old symdefs that have new offsets. */
  2342. X+   for (i = 0; i < num_old_symdefs; i++)
  2343. X+     if (newoffsets[i] != 0)
  2344. X+       old_symdefs[i].offset = newoffsets[i];
  2345. X+ 
  2346. X+   free (newoffsets);
  2347. X+   newoffsets = 0;
  2348. X+ 
  2349. X+ #if DEBUG
  2350. X+   verify_symdefs (map, old_symdefs, num_old_symdefs, old_strings);
  2351. X+ #endif
  2352. X+ 
  2353. X    /* Generate new, combined string table and put each string's offset into the
  2354. X       symdef that refers to it.  Note that old symdefs ref their strings by
  2355. X       offsets into old_strings but new symdefs contain addresses of strings.  */
  2356. X***************
  2357. X*** 1863,1869 ****
  2358. X  {
  2359. X    error (s1, s2);
  2360. X    fprintf (stderr, "\
  2361. X! Usage: ar [d|m|p|q|r|t|x [[abi [position-name] [cilouv]] archive file...\n");
  2362. X    exit (1);
  2363. X  }
  2364. X  
  2365. X--- 2214,2220 ----
  2366. X  {
  2367. X    error (s1, s2);
  2368. X    fprintf (stderr, "\
  2369. X! Usage: ar d|m|p|q|r|t|x [abiclouv] [position-name] archive file...\n");
  2370. X    exit (1);
  2371. X  }
  2372. X  
  2373. X***************
  2374. X*** 1896,1904 ****
  2375. X    fprintf (stderr, "ar: ");
  2376. X    fprintf (stderr, string);
  2377. X    if (mapelt->info.offset != 0)
  2378. X!     fprintf (stderr, "%s(%s)", archive, mapelt->info.name);
  2379. X    else
  2380. X!     fprintf (stderr, "%s", mapelt->info.name);
  2381. X    fprintf (stderr, "\n");
  2382. X  }
  2383. X  
  2384. X--- 2247,2261 ----
  2385. X    fprintf (stderr, "ar: ");
  2386. X    fprintf (stderr, string);
  2387. X    if (mapelt->info.offset != 0)
  2388. X!     {
  2389. X!       assert (mapelt->info.name.stored != NULL);
  2390. X!       fprintf (stderr, "%s(%s)", archive, mapelt->info.name.stored);
  2391. X!     }
  2392. X    else
  2393. X!     {
  2394. X!       assert (mapelt->info.name.given != NULL);
  2395. X!       fprintf (stderr, "%s", mapelt->info.name.given);
  2396. X!     }
  2397. X    fprintf (stderr, "\n");
  2398. X  }
  2399. X  
  2400. X***************
  2401. X*** 1975,1990 ****
  2402. X    return result;
  2403. X  }
  2404. X  
  2405. X! #ifdef    USG
  2406. X  int
  2407. X! rename (from, to)
  2408. X!      char *from, *to;
  2409. X  {
  2410. X!   (void)unlink (to);
  2411. X!   if (link (from, to) < 0
  2412. X!       || unlink (from) < 0)
  2413. X!     return -1;
  2414. X!   else
  2415. X      return 0;
  2416. X  }
  2417. X! #endif
  2418. X--- 2332,2478 ----
  2419. X    return result;
  2420. X  }
  2421. X  
  2422. X! 
  2423. X! /* Operations on member_names: */
  2424. X! 
  2425. X! /* Convert USER_NAME, possibly a path, into the name that goes into
  2426. X!    the archive header.  This involves stripping off leading path
  2427. X!    information and truncating the final name according to the desired
  2428. X!    rules.  The caller is responsible for freeing the returned string. */
  2429. X! 
  2430. X! char *
  2431. X! user_to_header(user_name)
  2432. X!      char *user_name;
  2433. X! {
  2434. X!   int namelen;
  2435. X!   struct ar_hdr dummy_hdr;
  2436. X!   char *result;
  2437. X!   char *tmp;
  2438. X!   char *file_name;        /* user name after removing initial path */
  2439. X! 
  2440. X!   /* Make a clean copy of the user name.  Bump the pointer past any
  2441. X!      leading path information.  */
  2442. X! 
  2443. X!   tmp = concat(user_name, "", "");
  2444. X! 
  2445. X!   user_name = rindex(tmp, '/');
  2446. X!   user_name = (user_name ? user_name + 1 : tmp);
  2447. X! 
  2448. X!   /* Save a copy of the file name, in case we need it for an error
  2449. X!      message later. */
  2450. X!   file_name = concat (user_name, "", "");
  2451. X! 
  2452. X!   /* Truncate the name to fit the ar header size. */
  2453. X!   namelen = strlen (user_name);
  2454. X!   if (namelen >= sizeof (dummy_hdr.ar_name))
  2455. X!     {
  2456. X!       if (gnu_truncation
  2457. X!       && user_name[namelen - 2] == '.'
  2458. X!       && user_name[namelen - 1] == 'o')
  2459. X!     {
  2460. X!       user_name[sizeof (dummy_hdr.ar_name) - 3] = '.';
  2461. X!       user_name[sizeof (dummy_hdr.ar_name) - 2] = 'o';
  2462. X!     }
  2463. X!       user_name[sizeof (dummy_hdr.ar_name) - 1] = '\0';
  2464. X!       error ("Using member name `%s' for filename `%s'", user_name, file_name);
  2465. X!     }
  2466. X! 
  2467. X!   /* Now make a fresh copy to return to the user. */
  2468. X!   result = concat (user_name, "", "");
  2469. X! 
  2470. X!   free (tmp);
  2471. X!   free (file_name);
  2472. X!   return result;
  2473. X! }
  2474. X! 
  2475. X! /* Return non-zero if the member names match.  As a side effect, 
  2476. X!    propogates user names.  This side-effect is important for, e.g.,
  2477. X!    extracting named members.  */ 
  2478. X! 
  2479. X  int
  2480. X! name_match(name1, name2)
  2481. X!      struct member_name *name1, *name2;
  2482. X  {
  2483. X!   if (strcmp(name1->stored, name2->stored) !=0)
  2484. X      return 0;
  2485. X+ 
  2486. X+   /* They match. */
  2487. X+   if (name1->given && !name2->given)
  2488. X+     name2->given = concat (name1->given, "", "");
  2489. X+   if (name2->given && !name1->given)
  2490. X+     name1->given = concat (name2->given, "", "");
  2491. X+ 
  2492. X+   return 1;
  2493. X  }
  2494. X! 
  2495. X! /* Return an array of member names, from an argv-type array of user 
  2496. X!    names. */
  2497. X! 
  2498. X! struct member_name *
  2499. X! make_file_args (argvp, num_files)
  2500. X!      char **argvp;
  2501. X!      int num_files;            /* number of elements in argvp array */
  2502. X! {
  2503. X!   struct member_name *result, *name;
  2504. X! 
  2505. X!   result = (struct member_name *)xmalloc ((num_files + 1) *
  2506. X!                       sizeof (struct member_name));
  2507. X!   for (name = result; name < result + num_files; ++name, ++argvp)
  2508. X!     init_name (name, *argvp);
  2509. X! 
  2510. X!   name->given = NULL;
  2511. X!   name->stored = NULL;
  2512. X! 
  2513. X!   return result;
  2514. X! }
  2515. X! 
  2516. X! /* Initialize a member_name.  The caller is responsible for eventually
  2517. X!    freeing the allocated strings.  */
  2518. X! 
  2519. X! void
  2520. X! init_name (name_ptr, user_name)
  2521. X!      struct member_name *name_ptr;
  2522. X!      char *user_name;
  2523. X! {
  2524. X!   name_ptr->given = concat (user_name, "", "");
  2525. X!   name_ptr->stored = user_to_header (user_name);
  2526. X! }
  2527. X! 
  2528. X! void
  2529. X! free_name_strings (name_ptr)
  2530. X!      struct member_name *name_ptr;
  2531. X! {
  2532. X!   if (name_ptr->given)
  2533. X!     free (name_ptr->given);
  2534. X!   if (name_ptr->stored)
  2535. X!     free (name_ptr->stored);
  2536. X!   name_ptr->given = name_ptr->stored = NULL;
  2537. X! }
  2538. X! 
  2539. X! /* Methods for managing mapelt's. */
  2540. X! 
  2541. X! /* Initialize a map element: make sure the name is empty. */
  2542. X! 
  2543. X! void
  2544. X! init_elt (elt)
  2545. X!      struct mapelt *elt;
  2546. X! {
  2547. X!   elt->info.name.stored = elt->info.name.given = NULL;
  2548. X! }
  2549. X! 
  2550. X! /* Mark a map element for deletion by making the name empty.
  2551. X!    XXX - leaks some memory here. */
  2552. X! 
  2553. X! void
  2554. X! mark_as_deleted (elt)
  2555. X!      struct mapelt *elt;
  2556. X! {
  2557. X!   elt->info.name.stored = elt->info.name.given = NULL;
  2558. X! }
  2559. X! 
  2560. X! int
  2561. X! marked_for_deletion (elt)
  2562. X!      struct mapelt *elt;
  2563. X! {
  2564. X!   return Empty_Name(&elt->info.name);
  2565. X! }
  2566. ________This_Is_The_END________
  2567. if test `wc -l < ar.diffs` -ne 2549; then
  2568.     echo 'shar: ar.diffs was damaged during transit (should have been 2549 lines)'
  2569. fi
  2570. fi        ; : end of overwriting check
  2571. exit 0
  2572.